/*
 * Copyright (c) 2018-2999 九五云信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yami.shop.bean.model.Category;
import com.yami.shop.bean.model.CategoryLang;
import com.yami.shop.bean.param.CategoryScoreConfigParam;
import com.yami.shop.bean.param.ScoreConfigParam;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.i18n.LanguageEnum;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.dao.CategoryBrandMapper;
import com.yami.shop.dao.CategoryMapper;
import com.yami.shop.dao.CategoryPropMapper;
import com.yami.shop.dao.ProductMapper;
import com.yami.shop.service.CategoryLangService;
import com.yami.shop.service.CategoryService;
import com.yami.shop.service.SysConfigService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @author LGH
 */
@Service
@AllArgsConstructor
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService{

	private final CategoryMapper categoryMapper;
	private final ShopConfig shopConfig;

	private final CategoryBrandMapper categoryBrandMapper;

	private final CategoryPropMapper categoryPropMapper;

	private final ProductMapper productMapper;

	private SysConfigService sysConfigService;

	private final CategoryLangService categoryLangService;

	@Override
	@Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
	@Caching(evict = {
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.superiorId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
	})
	public void saveCategroy(Category category) {
		category.setRecTime(new Date());
		// 保存分类信息
		categoryMapper.insert(category);
		saveCategoryLang(category);
		insertBrandsAndAttributes(category);

		if (Objects.equals(category.getParentId(),Constant.CATEGORY_ID) && Objects.equals(category.getShopId(),Constant.PLATFORM_SHOP_ID)){
			this.changeScoreConfig();
		}
	}

	private void saveCategoryLang(Category category) {
		List<CategoryLang> categoryLangs = new ArrayList<>();
		Long categoryId = category.getCategoryId();
		String categoryName = category.getCategoryName();
		String categoryNameEn = category.getCategoryNameEn();
		// 中文分类
		CategoryLang categoryLang = new CategoryLang();
		categoryLang.setCategoryId(categoryId);
		categoryLang.setLang(LanguageEnum.LANGUAGE_ZH_CN.getLang());
		categoryLang.setCategoryName(categoryName);
		categoryLangs.add(categoryLang);
		// 英文分类
		CategoryLang categoryLangEn = new CategoryLang();
		categoryLangEn.setCategoryId(categoryId);
		categoryLangEn.setLang(LanguageEnum.LANGUAGE_EN.getLang());
		categoryLangEn.setCategoryName(StrUtil.isNotBlank(categoryNameEn) ? categoryNameEn: categoryName);
		categoryLangs.add(categoryLangEn);

		categoryLangService.saveBatch(categoryLangs);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
	@Caching(evict = {
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.superiorId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
	})
	public void updateCategroy(Category category) {
		Category categoryDB = categoryMapper.selectById(category.getCategoryId());
		category.setUpdateTime(new Date());
		Long shopId = categoryDB.getShopId();
		// 保存分类信息
		categoryMapper.updateById(category);
		// 更新分类语言表
		updateCategoryLang(category);
//		if (Objects.equals(categoryDB.getStatus(),1) && Objects.equals(category.getStatus(),0)){
//			if (Objects.equals(category.getParentId(), 0L)){
//				List<Category> categoriesList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, category.getCategoryId()));
//				for (Category categoryByParentId: categoriesList){
//					categoryByParentId.setStatus(0);
//					//从正常改为下线
//					productMapper.offlineProdByCategoryId(categoryByParentId.getCategoryId());
//				}
//				updateBatchById(categoriesList);
//			}else {
//				//从正常改为下线
//				productMapper.offlineProdByCategoryId(category.getCategoryId());
//			}
//		}
		if (Objects.equals(categoryDB.getStatus(),1) && Objects.equals(category.getStatus(),0)){
			List<Long> ids = new ArrayList<>();
			ids.add(category.getCategoryId());
			List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, category.getCategoryId()));
			// 如果是平台且不是第三级分类的情况下，还需进行查找子集操作
			if (CollectionUtils.isNotEmpty(categoryList) && categoryDB.getGrade() < 2 && Objects.equals(shopId,Constant.PLATFORM_SHOP_ID)){
				categoryList.forEach(item -> item.setStatus(0));
				// 获取所有的下级分类,将他们的子集全部下架
				List<Long> offlineIds = new ArrayList<>();
				for (Category categoryByParentId: categoryList){
					categoryByParentId.setStatus(0);
					offlineIds.add(categoryByParentId.getCategoryId());
				}
				// 如果下架的是一级分类，还需进行查找子集操作
				if(Objects.equals(category.getParentId(), 0L)){
					List<Category> childCategories = list(new LambdaQueryWrapper<Category>().in(Category::getParentId, offlineIds));
					if(CollectionUtils.isNotEmpty(childCategories) && categoryDB.getGrade() < 1) {
						for (Category childCategory : childCategories) {
							ids.add(childCategory.getCategoryId());
							childCategory.setStatus(0);
						}
						categoryList.addAll(childCategories);
					}
				}else{
					// 如果下架的是二级分类，直接放入下级分类id进行下架即可
					ids.addAll(offlineIds);
				}
				updateBatchById(categoryList);
			}
			//从正常改为下线
			// 批量修改已经下架的分类下的商品的状态
			if(CollectionUtils.isNotEmpty(ids)) {
				//从正常改为下线
				productMapper.offlineProdByCategoryId(ids,shopId);
			}
		}
		//修改积分配置中的分类数据
		if (!Objects.equals(category.getCategoryName(),category.getOldCategoryName())){
			this.changeScoreConfig();
		}
		// 先删除后增加
		deleteBrandsAndAttributes(category.getCategoryId());
		insertBrandsAndAttributes(category);

	}

	private void updateCategoryLang(Category category) {
		Long categoryId = category.getCategoryId();
		String categoryName = category.getCategoryName();
		String categoryNameEn = category.getCategoryNameEn();
		categoryLangService.update(new LambdaUpdateWrapper<CategoryLang>()
				.set(CategoryLang::getCategoryName, categoryName)
				.eq(CategoryLang::getLang, LanguageEnum.LANGUAGE_ZH_CN.getLang())
				.eq(CategoryLang::getCategoryId, categoryId));
		categoryLangService.update(new LambdaUpdateWrapper<CategoryLang>()
				.set(CategoryLang::getCategoryName, StrUtil.isNotBlank(categoryNameEn)?categoryNameEn:categoryName)
				.eq(CategoryLang::getLang, LanguageEnum.LANGUAGE_EN.getLang())
				.eq(CategoryLang::getCategoryId, categoryId));
	}



	@Override
	@Transactional(rollbackFor = Exception.class)
//	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId")
	@Caching(evict = {
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.superiorId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#category.parentId + ':' + #category.shopId"),
			@CacheEvict(cacheNames = "CategoryListByShopId", key = "#category.shopId + ':category'")
	})
	public void deleteCategroy(Category category) {
		categoryMapper.deleteById(category.getCategoryId());
		// 删除分类语言表
		removeCategoryLang(category);
		//修改积分配置中的分类数据
		if (Objects.equals(category.getParentId(),Constant.CATEGORY_ID)){
			this.changeScoreConfig();
		}
		deleteBrandsAndAttributes(category.getCategoryId());
	}

	private void removeCategoryLang(Category category) {
		Long categoryId = category.getCategoryId();
		categoryLangService.remove(new LambdaUpdateWrapper<CategoryLang>().eq(CategoryLang::getCategoryId,categoryId));
	}

	@Override
	public Category getCategoryByCategoryIdAndShopId(Long categoryId, Long shopId) {
//		Category category = categoryMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getCategoryId, categoryId).eq(Category::getShopId, shopId));
		Category category = categoryMapper.getCategory(categoryId, shopId);
		if (category == null) {
			// 无法获取分类信息
			throw new YamiShopBindException("yami.unable.get.classification");
		}
		return category;
	}

    @Override
    @Cacheable(cacheNames = "CategoryListByParentIdAndShopId", key = "#parentId + ':' + #shopId + ':' + #dbLang")
    public List<Category> listByParentIdAndShopId(Long parentId, Long shopId, Integer dbLang) {
	    // 如果是平台分类，则特殊处理
	    if(shopId == 0) {
            List<Category> categoriesTwo = categoryMapper.listByParentId(parentId, I18nMessage.getDbLang());
            List<Category> categoriesThree = categoryMapper.listThreeByParentId(parentId, I18nMessage.getDbLang());
            for (Category category : categoriesThree) {
                category.setPic(shopConfig.getDomain().getResourcesDomainName() + "/" + category.getPic());
                category.setIcon(shopConfig.getDomain().getResourcesDomainName() + "/" + category.getIcon());
            }
            //根据父类id分组，并放入对应得父类中
            if (CollectionUtils.isNotEmpty(categoriesThree) && CollectionUtils.isNotEmpty(categoriesTwo)) {
                Map<Long, List<Category>> categoryMap = categoriesThree.stream().collect(groupingBy(Category::getParentId));
                for (Category category : categoriesTwo) {
                    if (categoryMap.containsKey(category.getCategoryId())) {
                        List<Category> categories = categoryMap.get(category.getCategoryId());
                        category.setCategories(categories);
                    }
                }
            }
            return categoriesTwo;
        }else {
            return categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getShopId,shopId).eq(Category::getParentId,parentId).eq(Category::getStatus, 1).orderByAsc(Category::getSeq));
        }
    }

	@Override
	@Cacheable(cacheNames = "CategoryListByShopId", key = "#shopId + ':category'")
	public List<Category> listByShopId(Long shopId) {
		return categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getShopId,shopId));
	}

	@Override
	public Long getParentCategoryByParentId(Long parentId) {
		return categoryMapper.getParentCategoryByParentId(parentId);
	}
	@Override
	@CacheEvict(cacheNames = "CategoryListByParentIdAndShopId", key = "#parentId + ':' + #shopId + ':'  + #lang")
	public void removeCacheByParentIdAndLang( Long parentId,Long shopId, Integer lang) {

	}

    @Override
    public List<Category> categoryList(Category category) {
		return categoryMapper.categoryList(category);
    }
	@Override
	public List<Category> listByLang(Integer lang, Integer maxGrade, Long parentId, Integer status, Long shopId) {
		return categoryMapper.listByLang(lang,maxGrade,parentId,status,shopId);
	}

	@Override
	public Integer getCategoryName(Category category) {
		return categoryMapper.getCategoryName(category);
	}

	@Override
	public Category getCategoryByCategoryId(Long categoryId) {
		return getCategoryByCategoryIdAndShopId(categoryId,null);
	}

	private void deleteBrandsAndAttributes(Long categoryId) {
		// 删除所有分类所关联的品牌
		categoryBrandMapper.deleteByCategoryId(categoryId);
		// 删除所有分类所关联的参数
		categoryPropMapper.deleteByCategoryId(categoryId);
	}

	private void insertBrandsAndAttributes(Category category) {
		//保存分类与品牌信息
		if(CollUtil.isNotEmpty(category.getBrandIds())){
			categoryBrandMapper.insertCategoryBrand(category.getCategoryId(), category.getBrandIds());
		}

		//保存分类与参数信息
		if(CollUtil.isNotEmpty(category.getAttributeIds())){
			categoryPropMapper.insertCategoryProp(category.getCategoryId(), category.getAttributeIds());
		}
	}

	/**
	 * 刷新积分配置中的分类数据
	 */
	private void changeScoreConfig(){
		ScoreConfigParam scoreParamDb = sysConfigService.getSysConfigObject(Constant.SCORE_CONFIG,ScoreConfigParam.class);
		if (Objects.isNull(scoreParamDb)){
			// 请先前往 【会员管理】-> 【积分成长值配置】-> 【积分获取配置】 进行配置并保存
			throw new YamiShopBindException("yami.flush.category.tips");
		}
		//判断分类数据是否正确
		List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>()
				.eq(Category::getParentId,Constant.CATEGORY_ID)
				.eq(Category::getShopId,Constant.PLATFORM_SHOP_ID)
				.orderByAsc(Category::getCategoryId)
		);
		Map<Long,Category> categoryMap = categoryList.stream().collect(Collectors.toMap(Category::getCategoryId,category -> category));
		// 还没有分类数据时，scoreParamDb.getCategoryConfigs()为null,所以为它new一个对象
		if (Objects.isNull(scoreParamDb.getCategoryConfigs())) {
			scoreParamDb.setCategoryConfigs(Lists.newArrayList());
		}
		Iterator<CategoryScoreConfigParam> iterator = scoreParamDb.getCategoryConfigs().iterator();
		//更新数据并去除已删除的数据
		while (iterator.hasNext()){
			CategoryScoreConfigParam categoryScoreConfigParam = iterator.next();
			Category category = categoryMap.get(categoryScoreConfigParam.getCategoryId());
			if (Objects.isNull(category)){
				iterator.remove();
			}else {
				//刷新分类名称
				categoryScoreConfigParam.setCategoryName(category.getCategoryName());
				//删除map中已进行操作过的分类
				categoryMap.remove(categoryScoreConfigParam.getCategoryId());
			}
		}
		// 获取map中剩下的分类的id（剩下的分类为积分配置json中所没有的分类，需要新增）
		Set<Long> longs = categoryMap.keySet();
		// 新增积分配置json中的分类数据
		for (Long catrgoryId:longs){
			Category category = categoryMap.get(catrgoryId);
			CategoryScoreConfigParam categoryScoreConfigParam = new CategoryScoreConfigParam();
			categoryScoreConfigParam.setCategoryId(category.getCategoryId());
			categoryScoreConfigParam.setCategoryName(category.getCategoryName());
			categoryScoreConfigParam.setGetScoreLimit(1.00);
			categoryScoreConfigParam.setUseScoreLimit(1.00);
			scoreParamDb.getCategoryConfigs().add(categoryScoreConfigParam);
		}
		//保存数据
		sysConfigService.saveOrUpdateSysConfigService(scoreParamDb,Constant.SCORE_CONFIG);
	}
}
